package com.inspectortime.mail.service;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.StringUtils;

import com.inspectortime.domain.EmailTemplate;
import com.inspectortime.domain.Inspection;
import com.inspectortime.domain.InspectorCompany;
import com.inspectortime.webapp.util.RequestPathUtils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Represents an e-mail message that is based on a String Freemarker template
 * 
 * @author mkvalsvik
 * 
 */
public class DynamicMailMessage extends AbstractMailMessage {

	private static final String FREEMARKER_TEMPLATE_NAME = "body";

	/**
	 * Construct a message from a persistable EmailTemplate which must contain
	 * an email body freemarker template
	 * 
	 * @param emailTemplate
	 *
	public DynamicMailMessage(EmailTemplate emailTemplate,
			Map<String, Object> data, String to) {
		this(emailTemplate.getBody(), data, to, emailTemplate.getSubject());
	}
	*/
	
	/**
	 * Construct a message from an email body freemarker template 
	 * TODO: Remove request parameter when root URL is configured in application.properties
	 * 
	 * @param bodyTemplate
	 */
	public DynamicMailMessage(String bodyTemplate, Inspection inspection, HttpServletRequest request, String to, String subject) {
		this.bodyTemplate = bodyTemplate;
		this.getData().put("inspection", inspection);
		this.getData().put("servletRequest", request);
		this.createHelperModel(getData());
		this.setTo(to);
		this.setSubject(subject);
	}

	public DynamicMailMessage(EmailTemplate emailTemplate, Inspection inspection, HttpServletRequest request, String to) {
		this(emailTemplate.getBody(), inspection, request, to, emailTemplate.getSubject());
	}
	
	private String bodyTemplate;

	/**
	 * Inspect the model map and create helper objects that allow for shorter
	 * template syntax. For instance, 'inspection.property.location.street1' can
	 * be accessed as 'address.street1'
	 */
	private void createHelperModel(Map<String, Object> map) {
		if (map.containsKey("inspection")) {
			Inspection inspection = (Inspection) map.get("inspection");
			map.put("time", inspection.getInspectionTime());
			map.put("property", inspection.getProperty());
			map.put("address", inspection.getProperty().getLocation());
			map.put("buyer", inspection.getHomeBuyer());
			map.put("inspector", inspection.getInspector());
			map.put("company", inspection.getInspector().getCompany());
			map.put("referringAgent", inspection.getReferringAgent());
		}
		if (map.containsKey("company") && map.containsKey("servletRequest")) {
			HttpServletRequest request = (HttpServletRequest) map.get("servletRequest");
			InspectorCompany company = (InspectorCompany) map.get("company");
			StringBuilder logoImg = new StringBuilder();
			logoImg.append("<img src='");
			logoImg.append(RequestPathUtils.constructLogoUrl(request, company
					.getShortName()));
			logoImg.append("' alt='/>");
			logoImg.append(company.getName());			
			logoImg.append("' />");
			map.put("logo", logoImg.toString());
		}
	}

	public String getBodyTemplate() {
		return bodyTemplate;
	}
	
	public String getBodyHtml() {
		return StringUtils.replace(this.getBody(), "\n", "<br/>\n");
	}

	public void setBodyTemplate(String bodyTemplate) {
		this.bodyTemplate = bodyTemplate;
	}

	public void processTemplates(Configuration freemarkerConfiguration)
			throws EmailDeliveryException {
		if (this.bodyTemplate == null) {
			return;
		}
		StringWriter writer = null;
		try {
			Template template = new Template(FREEMARKER_TEMPLATE_NAME,
					new StringReader(bodyTemplate), freemarkerConfiguration);
			writer = new StringWriter();
			template.process(getData(), writer);
			this.setBody(writer.toString());
		} catch (IOException e) {
			throw new RuntimeException("Unexpected IO error", e);
		} catch (TemplateException e) {
			throw new EmailDeliveryException(e.getMessage(), e);
		}
	}

}
